home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / lib / ruby / 1.8 / sync.rb < prev    next >
Text File  |  2008-09-19  |  6KB  |  313 lines

  1. #
  2. #   sync.rb - 2 phase lock with counter
  3. #       $Release Version: 1.0$
  4. #       $Revision: 11708 $
  5. #       $Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
  6. #       by Keiju ISHITSUKA(keiju@ishitsuka.com)
  7. #
  8. # --
  9. #  Sync_m, Synchronizer_m
  10. #  Usage:
  11. #   obj.extend(Sync_m)
  12. #   or
  13. #   class Foo
  14. #    include Sync_m
  15. #    :
  16. #   end
  17. #
  18. #   Sync_m#sync_mode
  19. #   Sync_m#sync_locked?, locked?
  20. #   Sync_m#sync_shared?, shared?
  21. #   Sync_m#sync_exclusive?, sync_exclusive?
  22. #   Sync_m#sync_try_lock, try_lock
  23. #   Sync_m#sync_lock, lock
  24. #   Sync_m#sync_unlock, unlock
  25. #
  26. #   Sync, Synchronicer:
  27. #    include Sync_m
  28. #   Usage:
  29. #   sync = Sync.new
  30. #
  31. #   Sync#mode
  32. #   Sync#locked?
  33. #   Sync#shared?
  34. #   Sync#exclusive?
  35. #   Sync#try_lock(mode) -- mode = :EX, :SH, :UN
  36. #   Sync#lock(mode)     -- mode = :EX, :SH, :UN
  37. #   Sync#unlock
  38. #   Sync#synchronize(mode) {...}
  39. #   
  40. #
  41.  
  42. unless defined? Thread
  43.   fail "Thread not available for this ruby interpreter"
  44. end
  45.  
  46. module Sync_m
  47.   RCS_ID='-$Header$-'
  48.   
  49.   # lock mode
  50.   UN = :UN
  51.   SH = :SH
  52.   EX = :EX
  53.   
  54.   # exceptions
  55.   class Err < StandardError
  56.     def Err.Fail(*opt)
  57.       Thread.critical = false
  58.       fail self, sprintf(self::Message, *opt)
  59.     end
  60.     
  61.     class UnknownLocker < Err
  62.       Message = "Thread(%s) not locked."
  63.       def UnknownLocker.Fail(th)
  64.     super(th.inspect)
  65.       end
  66.     end
  67.     
  68.     class LockModeFailer < Err
  69.       Message = "Unknown lock mode(%s)"
  70.       def LockModeFailer.Fail(mode)
  71.     if mode.id2name
  72.       mode = id2name
  73.     end
  74.     super(mode)
  75.       end
  76.     end
  77.   end
  78.   
  79.   def Sync_m.define_aliases(cl)
  80.     cl.module_eval %q{
  81.       alias locked? sync_locked?
  82.       alias shared? sync_shared?
  83.       alias exclusive? sync_exclusive?
  84.       alias lock sync_lock
  85.       alias unlock sync_unlock
  86.       alias try_lock sync_try_lock
  87.       alias synchronize sync_synchronize
  88.     }
  89.   end
  90.   
  91.   def Sync_m.append_features(cl)
  92.     super
  93.     unless cl.instance_of?(Module)
  94.       # do nothing for Modules
  95.       # make aliases and include the proper module.
  96.       define_aliases(cl)
  97.     end
  98.   end
  99.   
  100.   def Sync_m.extend_object(obj)
  101.     super
  102.     obj.sync_extended
  103.   end
  104.  
  105.   def sync_extended
  106.     unless (defined? locked? and
  107.         defined? shared? and
  108.         defined? exclusive? and
  109.         defined? lock and
  110.         defined? unlock and
  111.         defined? try_lock and
  112.         defined? synchronize)
  113.       Sync_m.define_aliases(class<<self;self;end)
  114.     end
  115.     sync_initialize
  116.   end
  117.  
  118.   # accessing
  119.   def sync_locked?
  120.     sync_mode != UN
  121.   end
  122.   
  123.   def sync_shared?
  124.     sync_mode == SH
  125.   end
  126.   
  127.   def sync_exclusive?
  128.     sync_mode == EX
  129.   end
  130.   
  131.   # locking methods.
  132.   def sync_try_lock(mode = EX)
  133.     return unlock if mode == UN
  134.     
  135.     Thread.critical = true
  136.     ret = sync_try_lock_sub(mode)
  137.     Thread.critical = false
  138.     ret
  139.   end
  140.   
  141.   def sync_lock(m = EX)
  142.     return unlock if m == UN
  143.  
  144.     until (Thread.critical = true; sync_try_lock_sub(m))
  145.       if sync_sh_locker[Thread.current]
  146.     sync_upgrade_waiting.push [Thread.current, sync_sh_locker[Thread.current]]
  147.     sync_sh_locker.delete(Thread.current)
  148.       else
  149.     sync_waiting.push Thread.current
  150.       end
  151.       Thread.stop
  152.     end
  153.     Thread.critical = false
  154.     self
  155.   end
  156.   
  157.   def sync_unlock(m = EX)
  158.     Thread.critical = true
  159.     if sync_mode == UN
  160.       Thread.critical = false
  161.       Err::UnknownLocker.Fail(Thread.current)
  162.     end
  163.     
  164.     m = sync_mode if m == EX and sync_mode == SH
  165.     
  166.     runnable = false
  167.     case m
  168.     when UN
  169.       Thread.critical = false
  170.       Err::UnknownLocker.Fail(Thread.current)
  171.       
  172.     when EX
  173.       if sync_ex_locker == Thread.current
  174.     if (self.sync_ex_count = sync_ex_count - 1) == 0
  175.       self.sync_ex_locker = nil
  176.       if sync_sh_locker.include?(Thread.current)
  177.         self.sync_mode = SH
  178.       else
  179.         self.sync_mode = UN
  180.       end
  181.       runnable = true
  182.     end
  183.       else
  184.     Err::UnknownLocker.Fail(Thread.current)
  185.       end
  186.       
  187.     when SH
  188.       if (count = sync_sh_locker[Thread.current]).nil?
  189.     Err::UnknownLocker.Fail(Thread.current)
  190.       else
  191.     if (sync_sh_locker[Thread.current] = count - 1) == 0 
  192.       sync_sh_locker.delete(Thread.current)
  193.       if sync_sh_locker.empty? and sync_ex_count == 0
  194.         self.sync_mode = UN
  195.         runnable = true
  196.       end
  197.     end
  198.       end
  199.     end
  200.     
  201.     if runnable
  202.       if sync_upgrade_waiting.size > 0
  203.     for k, v in sync_upgrade_waiting
  204.       sync_sh_locker[k] = v
  205.     end
  206.     wait = sync_upgrade_waiting
  207.     self.sync_upgrade_waiting = []
  208.     Thread.critical = false
  209.     
  210.     for w, v in wait
  211.       w.run
  212.     end
  213.       else
  214.     wait = sync_waiting
  215.     self.sync_waiting = []
  216.     Thread.critical = false
  217.     for w in wait
  218.       w.run
  219.     end
  220.       end
  221.     end
  222.     
  223.     Thread.critical = false
  224.     self
  225.   end
  226.   
  227.   def sync_synchronize(mode = EX)
  228.     begin
  229.       sync_lock(mode)
  230.       yield
  231.     ensure
  232.       sync_unlock
  233.     end
  234.   end
  235.  
  236.   attr :sync_mode, true
  237.     
  238.   attr :sync_waiting, true
  239.   attr :sync_upgrade_waiting, true
  240.   attr :sync_sh_locker, true
  241.   attr :sync_ex_locker, true
  242.   attr :sync_ex_count, true
  243.     
  244.   private
  245.  
  246.   def sync_initialize
  247.     @sync_mode = UN
  248.     @sync_waiting = []
  249.     @sync_upgrade_waiting = []
  250.     @sync_sh_locker = Hash.new
  251.     @sync_ex_locker = nil
  252.     @sync_ex_count = 0
  253.   end
  254.  
  255.   def initialize(*args)
  256.     sync_initialize
  257.     super
  258.   end
  259.     
  260.   def sync_try_lock_sub(m)
  261.     case m
  262.     when SH
  263.       case sync_mode
  264.       when UN
  265.     self.sync_mode = m
  266.     sync_sh_locker[Thread.current] = 1
  267.     ret = true
  268.       when SH
  269.     count = 0 unless count = sync_sh_locker[Thread.current]
  270.     sync_sh_locker[Thread.current] = count + 1
  271.     ret = true
  272.       when EX
  273.     # in EX mode, lock will upgrade to EX lock
  274.     if sync_ex_locker == Thread.current
  275.       self.sync_ex_count = sync_ex_count + 1
  276.       ret = true
  277.     else
  278.       ret = false
  279.     end
  280.       end
  281.     when EX
  282.       if sync_mode == UN or
  283.     sync_mode == SH && sync_sh_locker.size == 1 && sync_sh_locker.include?(Thread.current) 
  284.     self.sync_mode = m
  285.     self.sync_ex_locker = Thread.current
  286.     self.sync_ex_count = 1
  287.     ret = true
  288.       elsif sync_mode == EX && sync_ex_locker == Thread.current
  289.     self.sync_ex_count = sync_ex_count + 1
  290.     ret = true
  291.       else
  292.     ret = false
  293.       end
  294.     else
  295.       Thread.critical = false
  296.       Err::LockModeFailer.Fail mode
  297.     end
  298.     return ret
  299.   end
  300. end
  301. Synchronizer_m = Sync_m
  302.  
  303. class Sync
  304.   #Sync_m.extend_class self
  305.   include Sync_m
  306.     
  307.   def initialize
  308.     super
  309.   end
  310.     
  311. end
  312. Synchronizer = Sync
  313.